/******************************************************************************
 * * call_log_ui.c - UI display of call log module
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/

#include "call_log_global.h"

/**
 * common create function
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Create_Common(VOID *pDesc)
{
    g_Call_Log_Mng.CurrDesc = pDesc;
}

/**
 * common destroy function
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Destroy_Common(VOID *pDesc)
{
    Hal_Mem_Free(pDesc);
    g_Call_Log_Mng.CurrDesc = NULL;
}

/**
 * common function for destroy list only
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Destroy_ListOnly(VOID *pDesc)
{
    UI_Normal_List_Only_Desc_t *Desc = pDesc;

    Hal_Mem_Free(Desc->List.ButtonList);

    Call_Log_Destroy_Common(pDesc);
}

/**
 * common function for destroy container list
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Destroy_ContList(VOID *pDesc)
{
    UI_Normal_Container_List_Desc_t *Desc = pDesc;

    Hal_Mem_Free(Desc->ContList.ContainerList);

    Call_Log_Destroy_Common(pDesc);
}

/**
 * common restore state function
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Restore_Common(VOID *pDesc)
{
    g_Call_Log_Mng.CurrDesc = pDesc;
}

/**
 * set label text of Call_Log_Call_List
 * param (in) CallLog: Call_Log_Node_t *
 * param (in) Label1: lv_obj_t *
 * param (in) Label2: lv_obj_t *
 * return VOID
 */
static VOID Call_Log_Call_List_Set_Label_Txt(Call_Log_Node_t *CallLog, UI_Label_Desc_t *Label1, lv_obj_t *Label2)
{
    INT8      LabelTxt[48];
    hal_rtc_t Time;

    if (MMI_MODEM_SIM_1 == CallLog->Data.SimId)
    {
        lv_img_set_src(Label1->Img, SYMBOL_SIM1);
    }
    else
    {
        lv_img_set_src(Label1->Img, SYMBOL_SIM2);
    }
    if (0 < strlen(CallLog->Data.Name))
    {
        lv_label_set_text(Label1->Label, CallLog->Data.Name);
    }
    else
    {
        lv_label_set_text(Label1->Label, CallLog->Data.Number);
    }

    UI_Seconds_to_Time(CallLog->Data.Timestamp, &Time);
    sprintf(LabelTxt, "%02d/%02d  %02d:%02d", Time.tm_mon, Time.tm_mday, Time.tm_hour, Time.tm_min);
    lv_label_set_text(Label2, LabelTxt);  // Time
}

/**
 * set label text of Call_Log_Call_List
 * param (in) pDesc: UI_Normal_Container_List_Desc_t *
 * return VOID
 */
VOID Call_Log_Call_List_Set_Label(UI_Normal_Container_List_Desc_t *pDesc)
{
    Call_Log_Node_t *CallLog = NULL;
    UINT8           Index    = 0;
    INT8            i        = 0;

    /* set label - [ContListIndex, ListContainerCnt] */
    i       = pDesc->ContList.Index;
    CallLog = g_Call_Log_Mng.CurrCallLog;

    while (CallLog)
    {
        if (g_Call_Log_Mng.CurrType == CallLog->Data.Type)
        {
            Index = i;
            Call_Log_Call_List_Set_Label_Txt(CallLog, &pDesc->ContList.ContainerList[Index].Label, pDesc->ContList.ContainerList[Index].u.Label2.Label);

            if (++i >= pDesc->ContList.ListContainerCnt)
            {
                break;
            }
        }
        CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLog);
    }

    /* set label - (ContListIndex, 0] */
    i = pDesc->ContList.Index - 1;
    if (i >= 0)
    {
        CallLog = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.CurrCallLog);

        while (CallLog)
        {
            if (g_Call_Log_Mng.CurrType == CallLog->Data.Type)
            {
                Index = i;
                Call_Log_Call_List_Set_Label_Txt(CallLog, &pDesc->ContList.ContainerList[Index].Label, pDesc->ContList.ContainerList[Index].u.Label2.Label);

                if (--i < 0)
                {
                    break;
                }
            }
            CallLog = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLog);
        }
    }
} /* Call_Log_Call_List_Set_Label */

/**
 * create function of Call_Log_Call_List
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Call_List_Create(VOID *pDesc)
{
    Call_Log_Create_Common(pDesc);
    Call_Log_Call_List_Set_Label(pDesc);
}

/**
 * restore function of Call_Log_Call_List
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Call_List_Restore(VOID *pDesc)
{
    Call_Log_Restore_Common(pDesc);
    Call_Log_Call_List_Set_Label(pDesc);
}

/**
 * set title of Call_Log_Opt
 * param (in) pDesc: UI_Normal_List_Only_Desc_t *
 * return VOID
 */
static VOID Call_Log_Opt_Set_Title(UI_Normal_List_Only_Desc_t *pDesc)
{
    if (g_Call_Log_Mng.CurrCallLog)
    {
        if (strlen(g_Call_Log_Mng.CurrCallLog->Data.Name) > 0)
        {
            lv_label_set_text(pDesc->TitleBar.Label, g_Call_Log_Mng.CurrCallLog->Data.Name);
        }
        else
        {
            lv_label_set_text(pDesc->TitleBar.Label, g_Call_Log_Mng.CurrCallLog->Data.Number);
        }
    }

    lv_label_set_align(pDesc->TitleBar.Label, LV_LABEL_ALIGN_CENTER);
}

/**
 * create function of Call_Log_Opt
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Opt_Create(VOID *pDesc)
{
    Call_Log_Create_Common(pDesc);
    Call_Log_Opt_Set_Title(pDesc);
}

/**
 * restore function of Call_Log_Opt
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_Opt_Restore(VOID *pDesc)
{
    Call_Log_Restore_Common(pDesc);
    Call_Log_Opt_Set_Title(pDesc);
}

/**
 * set label text of Call_Log_History_List
 * param (in) CallLog: Call_Log_Node_t *
 * param (in) Label1: lv_obj_t *
 * param (in) Label2: lv_obj_t *
 * return VOID
 */
static VOID Call_Log_History_List_Set_Label_Txt(Call_Log_Node_t *CallLog, UI_Label_Desc_t *Label1, lv_obj_t *Label2)
{
    INT8      LabelTxt[48];
    hal_rtc_t Time;

    if (MMI_MODEM_SIM_1 == CallLog->Data.SimId)
    {
        lv_img_set_src(Label1->Img, SYMBOL_SIM1);
    }
    else
    {
        lv_img_set_src(Label1->Img, SYMBOL_SIM2);
    }
    lv_label_set_text(Label1->Label, CallLog->Data.Number);

    UI_Seconds_to_Time(CallLog->Data.Timestamp, &Time);
    sprintf(LabelTxt, "%02d/%02d  %02d:%02d", Time.tm_mon, Time.tm_mday, Time.tm_hour, Time.tm_min);
    lv_label_set_text(Label2, LabelTxt);  // Time
}

/**
 * set label text of Call_Log_History_List
 * param (in) pDesc: UI_Normal_Container_List_Desc_t *
 * return VOID
 */
VOID Call_Log_History_List_Set_Label(UI_Normal_Container_List_Desc_t *pDesc)
{
    Call_Log_Node_t *CallLog = NULL;
    UINT8           Index    = 0;
    INT8            i        = 0;

    /* set title */
    if (strlen(g_Call_Log_Mng.CurrCallLog->Data.Name) > 0)
    {
        lv_label_set_text(pDesc->TitleBar.Label, g_Call_Log_Mng.CurrCallLog->Data.Name);
        lv_label_set_align(pDesc->TitleBar.Label, LV_LABEL_ALIGN_CENTER);
    }

    /* set label - [ContListIndex, ListContainerCnt] */
    i       = pDesc->ContList.Index;
    CallLog = g_Call_Log_Mng.HisCallLog;

    while (CallLog)
    {
        if (  (g_Call_Log_Mng.CurrType == CallLog->Data.Type)
           && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLog->Data.Number)))
        {
            Index = i;
            Call_Log_History_List_Set_Label_Txt(CallLog, &pDesc->ContList.ContainerList[Index].Label, pDesc->ContList.ContainerList[Index].u.Label2.Label);

            if (++i >= pDesc->ContList.ListContainerCnt)
            {
                break;
            }
        }
        CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLog);
    }

    /* set label - (ContListIndex, 0] */
    i = pDesc->ContList.Index - 1;
    if (i >= 0)
    {
        CallLog = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.HisCallLog);

        while (CallLog)
        {
            if (  (g_Call_Log_Mng.CurrType == CallLog->Data.Type)
               && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLog->Data.Number)))
            {
                Index = i;
                Call_Log_History_List_Set_Label_Txt(CallLog, &pDesc->ContList.ContainerList[Index].Label, pDesc->ContList.ContainerList[Index].u.Label2.Label);

                if (--i < 0)
                {
                    break;
                }
            }
            CallLog = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLog);
        }
    }
} /* Call_Log_History_List_Set_Label */

/**
 * create function of Call_Log_History_List
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_History_List_Create(VOID *pDesc)
{
    Call_Log_Create_Common(pDesc);
    Call_Log_History_List_Set_Label(pDesc);
}

/**
 * restore function of Call_Log_History_List
 * param (in) pDesc: VOID *
 * return VOID
 */
static VOID Call_Log_History_List_Restore(VOID *pDesc)
{
    Call_Log_Restore_Common(pDesc);
    Call_Log_History_List_Set_Label(pDesc);
}

/**
 * display Call_Log_Menu
 */
VOID Display_Call_Log_Menu(VOID)
{
    Nav_Func_List_t            FuncList;
    UI_Normal_List_Only_Desc_t *pDesc = NULL;
    UINT32                     Size   = 0;
    UINT8                      i      = 0;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_List_Only_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_ListOnly;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    pDesc->TitleBar.TxtId    = PHONE_TEXT_ID_CALLLOG;
    pDesc->TitleBar.TxtAlign = LV_LABEL_ALIGN_CENTER;

    pDesc->List.ListButtonCnt = 4;
    Size                      = sizeof(UI_Button_Desc_t) * pDesc->List.ListButtonCnt;
    pDesc->List.ButtonList    = (UI_Button_Desc_t *)Hal_Mem_Alloc(Size);
    memset(pDesc->List.ButtonList, 0, Size);

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_MISSED_CALLS;
    pDesc->List.ButtonList[i].SymbolId1    = SYMBOL_MISSED;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Missed_Calls;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_RECEIVED_CALLS;
    pDesc->List.ButtonList[i].SymbolId1    = SYMBOL_RECEIVED;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Received_Calls;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_DAIL;
    pDesc->List.ButtonList[i].SymbolId1    = SYMBOL_DIALED;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Dialled_Calls;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_DEL_RECENT_CALL;
    pDesc->List.ButtonList[i].SymbolId1    = SYMBOL_TRASH;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Del_Recent_Calls;

    pDesc->BtnBar.ButtonM.Valid = TRUE;
    pDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_SELECT;
    pDesc->BtnBar.ButtonR.Valid = TRUE;
    pDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    pDesc->KeyFunc              = Call_Log_Proc_Key_Menu;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_MENU, &FuncList, pDesc);
} /* Display_Call_Log_Menu */

/**
 * display Call_Log_No_Numbers
 */
VOID Display_Call_Log_No_Numbers(VOID)
{
    Nav_Func_List_t  FuncList;
    UI_Status_Desc_t *pDesc = NULL;

    FuncList.OnShow         = (Void_P_Func_t)UI_Status_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_Common;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    memset(pDesc, 0, sizeof(UI_Status_Desc_t));
    pDesc->ContLabel.TxtId = PHONE_TEXT_ID_NO_NUMBERS;    // No numbers
    pDesc->ContLabelAlign  = LV_ALIGN_IN_TOP_LEFT;
    pDesc->KeyFunc         = Call_Log_Proc_Key_Status;

    g_Call_Log_Mng.ActStatus = ACT_ID_CALL_LOG_NO_NUMBERS;
    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_NO_NUMBERS, &FuncList, pDesc);

    // Start timer
    g_Call_Log_Mng.DisplayTimer = Hal_Timer_Start(UI_CALL_LOG_TIMER_LEN, Call_Log_Proc_Status_Timeout, (VOID *)&g_Call_Log_Mng.ActStatus, FALSE);
}

/**
 * display Call_Log_No_Dialled_Numbers
 */
VOID Display_Call_Log_No_Dialled_Numbers(VOID)
{
    Nav_Func_List_t             FuncList;
    UI_Normal_Label_Only_Desc_t *pDesc = NULL;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_Label_Only_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_Common;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Normal_Label_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_Label_Only_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_Label_Only_Desc_t));
    pDesc->TitleBar.TxtId          = PHONE_TEXT_ID_DAIL;       // Dialled numbers
    pDesc->TitleBar.TxtAlign       = LV_LABEL_ALIGN_CENTER;
    pDesc->ContLabel.TxtId         = PHONE_TEXT_ID_NO_NUMBERS; // No numbers
    pDesc->ButtonBar.ButtonR.Valid = TRUE;
    pDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_EXIT;
    pDesc->KeyFunc                 = Call_Log_Proc_Key_No_Dialled_Numbers;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_NO_DIALLED_NUMBERS, &FuncList, pDesc);
}

/**
 * display Call_Log_Call_List
 * param (in) Type: CALL_LOG_TYPE
 * param (in) NavForward: BOOL
 * param (in) SrcActId: ACTIVITY_ID
 * return VOID
 */
VOID Display_Call_Log_Call_List(CALL_LOG_TYPE Type, BOOL NavForward, ACTIVITY_ID SrcActId)
{
    Nav_Func_List_t                 FuncList;
    UI_Normal_Container_List_Desc_t *pDesc   = NULL;
    Call_Log_Node_t                 *CallLog = NULL;
    UINT16                          Title;
    UINT16                          Index   = 0;
    UINT16                          CallCnt = 0;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_Container_List_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Call_List_Create;
    FuncList.OnDestroy      = Call_Log_Destroy_ContList;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Call_List_Restore;

    pDesc = (UI_Normal_Container_List_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_Container_List_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_Container_List_Desc_t));

    /* get call log count */
    switch (Type)
    {
    case CALL_LOG_TYPE_MISSED:
        Title   = PHONE_TEXT_ID_MISSED_CALLS;
        CallCnt = g_Call_Log_Mng.MissedCalls;

        if (g_Call_Log_Mng.UnreadMissedCalls > 0)
        {
            /* clear UnreadMissedCalls */
            g_Call_Log_Mng.UnreadMissedCalls = 0;
            UINT32 Offset = NV_CALL_LOG_MAX_NUM * sizeof(NV_Call_Log_Data_t);
            UI_NV_Write_Req(NV_SECTION_UI_CALL_LOG, Offset, 1, &g_Call_Log_Mng.UnreadMissedCalls);

            /* indicate framework the missed calls have been read */
            Framework_CallLog_Missed_Call_Read_Ind();
        }
        break;

    case CALL_LOG_TYPE_RECEIVED:
        Title   = PHONE_TEXT_ID_RECEIVED_CALL;
        CallCnt = g_Call_Log_Mng.ReceivedCalls;
        break;

    case CALL_LOG_TYPE_DIALLED:
        Title   = PHONE_TEXT_ID_DAIL;
        CallCnt = g_Call_Log_Mng.DialledCalls;
        break;

    default:
        break;
    }

    /* set container count in the list */
    pDesc->ContList.ListContainerCnt = (CallCnt > CALL_LOG_LIST_CONT_CNT ? CALL_LOG_LIST_CONT_CNT : CallCnt);

    /* set current type */
    g_Call_Log_Mng.CurrType = Type;

    if (NULL == g_Call_Log_Mng.CurrCallLog)
    {
        /* set current call log to the 1st one */
        CallLog = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);
        while (CallLog)
        {
            if (Type == CallLog->Data.Type)
            {
                break;
            }
            CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLog);
        }
        g_Call_Log_Mng.CurrCallLog = CallLog;

        /* set container select index */
        pDesc->ContList.Index = 0;
    }
    else    /* after delete number from list */
    {
        CallLog = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);
        while (CallLog)
        {
            if (g_Call_Log_Mng.CurrCallLog == CallLog)
            {
                break;
            }
            else
            {
                Index++;
            }
            CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLog);
        }

        /* set container select index */
        pDesc->ContList.Index = (Index >= pDesc->ContList.ListContainerCnt ? (pDesc->ContList.ListContainerCnt - 1) : Index);
    }

    pDesc->TitleBar.TxtId         = Title;
    pDesc->TitleBar.TxtAlign      = LV_LABEL_ALIGN_CENTER;
    pDesc->ContList.ContainerList = (UI_Container_Base_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Container_Base_Desc_t) * pDesc->ContList.ListContainerCnt);
    Hal_Mem_Set(pDesc->ContList.ContainerList, 0, sizeof(UI_Container_Base_Desc_t) * pDesc->ContList.ListContainerCnt);

    for (UINT8 i = 0; i < pDesc->ContList.ListContainerCnt; i++)
    {
        pDesc->ContList.ContainerList[i].Valid             = TRUE;
        pDesc->ContList.ContainerList[i].Label.TxtId       = LV_LANG_TXT_ID_NONE; // SIM ID + Name/Number
        pDesc->ContList.ContainerList[i].Label.TxtAlign    = LV_LABEL_ALIGN_LEFT;
        pDesc->ContList.ContainerList[i].Label.ImgSrc      = SYMBOL_SIM1;
        pDesc->ContList.ContainerList[i].Choise            = UI_BASE_OBJ_LABEL;
        pDesc->ContList.ContainerList[i].u.Label2.TxtId    = LV_LANG_TXT_ID_NONE; // Call Time
        pDesc->ContList.ContainerList[i].u.Label2.TxtAlign = LV_LABEL_ALIGN_LEFT;
        pDesc->ContList.ContainerList[i].ReleaseFunc       = NULL;
    }

    pDesc->ButtonBar.ButtonL.Valid = TRUE;
    pDesc->ButtonBar.ButtonL.TxtId = PHONE_TEXT_ID_OPT;
    pDesc->ButtonBar.ButtonR.Valid = TRUE;
    pDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    pDesc->KeyFunc                 = Call_Log_Proc_Key_Call_List;

    if (NavForward)
    {
        g_Call_Log_Mng.ActBeforeCallList = Nav_Get_Top();
        Nav_Forward(SrcActId, ACT_ID_CALL_LOG_CALL_LIST, &FuncList, pDesc);
    }
    else
    {
        Nav_Backward_And_Forward(SrcActId, g_Call_Log_Mng.ActBeforeCallList, ACT_ID_CALL_LOG_CALL_LIST, &FuncList, pDesc);
    }
} /* Display_Call_Log_Call_List */

/**
 * display Call_Log_Opt
 */
VOID Display_Call_Log_Opt(VOID)
{
    Nav_Func_List_t            FuncList;
    UI_Normal_List_Only_Desc_t *pDesc = NULL;
    UINT32                     Size   = 0;
    UINT8                      i      = 0;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_List_Only_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Opt_Create;
    FuncList.OnDestroy      = Call_Log_Destroy_ListOnly;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Opt_Restore;

    pDesc = (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    pDesc->TitleBar.TxtId     = LV_LANG_TXT_ID_NONE; // Name or Number
    pDesc->List.ListButtonCnt = 7;
    Size                      = sizeof(UI_Button_Desc_t) * pDesc->List.ListButtonCnt;
    pDesc->List.ButtonList    = (UI_Button_Desc_t *)Hal_Mem_Alloc(Size);
    memset(pDesc->List.ButtonList, 0, Size);

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_CALL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Call;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_CALL_HIS;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Call_History;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_SEND_SMS;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Send_Sms;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_SEND_NUM;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Send_Number;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_SAVE;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Save_Number;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_DEL_RECENT_CALL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Del_Number;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_ADD_TO_SL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Add_To_Scrn_List;

    pDesc->BtnBar.ButtonM.Valid = TRUE;
    pDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_SELECT;
    pDesc->BtnBar.ButtonR.Valid = TRUE;
    pDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    pDesc->KeyFunc              = Call_Log_Proc_Key_Opt;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_OPT, &FuncList, pDesc);
} /* Display_Call_Log_Opt */

/**
 * display Call_Log_History_List
 */
VOID Display_Call_Log_History_List(VOID)
{
    Nav_Func_List_t                 FuncList;
    UI_Normal_Container_List_Desc_t *pDesc       = NULL;
    Call_Log_Node_t                 *CallLog     = NULL;
    BOOL                            FirstCallLog = FALSE;
    UINT16                          CallCnt      = 0;
    UINT32                          Size         = 0;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_Container_List_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_History_List_Create;
    FuncList.OnDestroy      = Call_Log_Destroy_ContList;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_History_List_Restore;

    pDesc = (UI_Normal_Container_List_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_Container_List_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_Container_List_Desc_t));

    /* caculate call count, and set HisCallLog */
    CallLog = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);
    while (CallLog)
    {
        if (  (CallLog->Data.Type == g_Call_Log_Mng.CurrType)
           && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLog->Data.Number)))
        {
            if (!FirstCallLog)
            {
                FirstCallLog              = TRUE;
                g_Call_Log_Mng.HisCallLog = CallLog;   // set to the first history call log
            }
            CallCnt++;
        }
        CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLog);
    }

    pDesc->TitleBar.TxtId            = LV_LANG_TXT_ID_NONE; // Name
    pDesc->ContList.ListContainerCnt = (CallCnt > CALL_LOG_LIST_CONT_CNT ? CALL_LOG_LIST_CONT_CNT : CallCnt);
    Size                             = sizeof(UI_Container_Base_Desc_t) * pDesc->ContList.ListContainerCnt;
    pDesc->ContList.ContainerList    = (UI_Container_Base_Desc_t *)Hal_Mem_Alloc(Size);
    memset(pDesc->ContList.ContainerList, 0, Size);

    for (UINT8 i = 0; i < pDesc->ContList.ListContainerCnt; i++)
    {
        pDesc->ContList.ContainerList[i].Valid             = TRUE;
        pDesc->ContList.ContainerList[i].Label.TxtId       = LV_LANG_TXT_ID_NONE; // Number
        pDesc->ContList.ContainerList[i].Label.TxtAlign    = LV_LABEL_ALIGN_LEFT;
        pDesc->ContList.ContainerList[i].Choise            = UI_BASE_OBJ_LABEL;
        pDesc->ContList.ContainerList[i].u.Label2.TxtId    = LV_LANG_TXT_ID_NONE; // Call Time
        pDesc->ContList.ContainerList[i].u.Label2.TxtAlign = LV_LABEL_ALIGN_LEFT;
        pDesc->ContList.ContainerList[i].ReleaseFunc       = NULL;
    }

    pDesc->ButtonBar.ButtonR.Valid = TRUE;
    pDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    pDesc->KeyFunc                 = Call_Log_Proc_Key_History_List;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_HISTORY_LIST, &FuncList, pDesc);
} /* Display_Call_Log_History_List */

/**
 * display Call_Log_Delete_Number_Inquire
 */
VOID Display_Call_Log_Delete_Number_Inquire(VOID)
{
    Nav_Func_List_t          FuncList;
    UI_Normal_NoTitle_Desc_t *pDesc = NULL;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_NoTitle_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_Common;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Normal_NoTitle_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_NoTitle_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_NoTitle_Desc_t));
    pDesc->ContenCont.ContLabel.TxtId = PHONE_TEXT_ID_DEL_NUM_FROM_LIST_Q;
    pDesc->ButtonBar.ButtonM.Valid    = TRUE;
    pDesc->ButtonBar.ButtonM.TxtId    = PHONE_TEXT_ID_OK;
    pDesc->ButtonBar.ButtonR.Valid    = TRUE;
    pDesc->ButtonBar.ButtonR.TxtId    = PHONE_TEXT_ID_BACK;
    pDesc->KeyFunc                    = Call_Log_Proc_Key_Delete_Number_Inquire;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_DELETE_NUMBER_INQUIRE, &FuncList, pDesc);
}

/**
 * display Call_Log_Delete_Number_Done
 */
VOID Display_Call_Log_Delete_Number_Done(VOID)
{
    Nav_Func_List_t  FuncList;
    UI_Status_Desc_t *pDesc = NULL;

    FuncList.OnShow         = (Void_P_Func_t)UI_Status_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_Common;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    memset(pDesc, 0, sizeof(UI_Status_Desc_t));
    pDesc->ContLabel.TxtId = PHONE_TEXT_ID_DELETED;    // Deleted
    pDesc->ContLabelAlign  = LV_ALIGN_IN_TOP_LEFT;
    pDesc->KeyFunc         = Call_Log_Proc_Key_Status;

    g_Call_Log_Mng.ActStatus = ACT_ID_CALL_LOG_DELETE_NUMBER_DONE;
    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_DELETE_NUMBER_DONE, &FuncList, pDesc);

    // Start timer
    g_Call_Log_Mng.DisplayTimer = Hal_Timer_Start(UI_CALL_LOG_TIMER_LEN, Call_Log_Proc_Status_Timeout, (VOID *)&g_Call_Log_Mng.ActStatus, FALSE);
}

/**
 * display Call_Log_Delete_List
 */
VOID Display_Call_Log_Delete_List(VOID)
{
    Nav_Func_List_t            FuncList;
    UI_Normal_List_Only_Desc_t *pDesc = NULL;
    UINT32                     Size   = 0;
    UINT8                      i      = 0;

    FuncList.OnShow         = (Void_P_Func_t)UI_Normal_List_Only_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_ListOnly;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    memset(pDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    pDesc->TitleBar.TxtId     = PHONE_TEXT_ID_DEL_RECENT_CALL;
    pDesc->TitleBar.TxtAlign  = LV_LABEL_ALIGN_CENTER;
    pDesc->List.ListButtonCnt = 4;
    Size                      = sizeof(UI_Button_Desc_t) * pDesc->List.ListButtonCnt;
    pDesc->List.ButtonList    = (UI_Button_Desc_t *)Hal_Mem_Alloc(Size);
    memset(pDesc->List.ButtonList, 0, Size);

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_ALL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Del_All;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_MISSED_CALL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Del_Missed;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_RECEIVED_CALL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Del_Received;

    pDesc->List.ButtonList[i].Valid        = TRUE;
    pDesc->List.ButtonList[i].ButtonIndex  = i;
    pDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_DIALLED_CALL;
    pDesc->List.ButtonList[i++].ReleaseFun = Call_Log_Proc_Btn_Del_Dialled;

    pDesc->BtnBar.ButtonM.Valid = TRUE;
    pDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_OK;
    pDesc->BtnBar.ButtonR.Valid = TRUE;
    pDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    pDesc->KeyFunc              = Call_Log_Proc_Key_Delete_List;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_DELETE_LIST, &FuncList, pDesc);
} /* Display_Call_Log_Delete_List */

/**
 * display Call_Log_Delete_List_Done
 */
VOID Display_Call_Log_Delete_List_Done(VOID)
{
    Nav_Func_List_t  FuncList;
    UI_Status_Desc_t *pDesc = NULL;

    FuncList.OnShow         = (Void_P_Func_t)UI_Status_Create;
    FuncList.OnHide         = NULL;
    FuncList.OnCreate       = Call_Log_Create_Common;
    FuncList.OnDestroy      = Call_Log_Destroy_Common;
    FuncList.OnSaveState    = NULL;
    FuncList.OnRestoreState = Call_Log_Restore_Common;

    pDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    memset(pDesc, 0, sizeof(UI_Status_Desc_t));
    pDesc->ContLabel.TxtId = PHONE_TEXT_ID_DELETED;    // Deleted
    pDesc->ContLabelAlign  = LV_ALIGN_IN_TOP_LEFT;
    pDesc->KeyFunc         = Call_Log_Proc_Key_Status;

    g_Call_Log_Mng.ActStatus = ACT_ID_CALL_LOG_DELETE_LIST_DONE;
    Nav_Forward(ACT_ID_ANY, ACT_ID_CALL_LOG_DELETE_LIST_DONE, &FuncList, pDesc);

    // Start timer
    g_Call_Log_Mng.DisplayTimer = Hal_Timer_Start(UI_CALL_LOG_TIMER_LEN, Call_Log_Proc_Status_Timeout, (VOID *)&g_Call_Log_Mng.ActStatus, FALSE);
}
